﻿using System;
using System.ComponentModel;
using System.Reflection;
using System.Web;
using System.Web.UI;
using DigitalSum.Web.Extensions;

namespace DigitalSum.Web.UI.WebControls
{
    public class ControlParameter : System.Web.UI.WebControls.Parameter
    {
        #region FIELDS
        private string _controlID;
        //private string _containerID;
        private ControlParameterLookupOptions _lookupOptions;

        #endregion

        #region PROPERTIES

        public new string ControlID
        {
            get;
            set;
        }

        public new string PropertyName
        {
            get;
            set;
        }

        public class ControlParameterLookupOptions
        {
            private object _control;
            private string _containerID;

            internal ControlParameterLookupOptions(object control)
            {
                _control = control;
            }

            public string PropertyName
            {
                get;
                set;
            }

            public string ContainerID
            {
                get { return _containerID; }
                set { _containerID = value; }
            }
        }

        [Description("")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("Client-Side")]
        [MergableProperty(false)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public ControlParameterLookupOptions LookupOptions
        {
            get
            {
                if (_lookupOptions == null)
                    _lookupOptions = new ControlParameterLookupOptions(this);

                return _lookupOptions;
            }
        }

        #endregion

        #region CONSTRUCTORS
        public ControlParameter() : base() { _Init(); }

        public ControlParameter(string name) : base(name) { _Init(); }

        public ControlParameter(string name, TypeCode type) : base(name, type) { _Init(); }

        public ControlParameter(string name, TypeCode type, string defaultValue) : base(name, type, defaultValue) { _Init(); }

        #region INITIALIZATIONS
        ContextManager _manager;

        private void _Init()
        {
            _manager = new ContextManager();
        }
        #endregion

        #endregion

        #region METHODS

        protected override object Evaluate(HttpContext context, Control control)
        {
            //Init();
            if (!_manager.Launched)
                return base.Evaluate(context, control);

            object value = null;

            try
            {
                Control container = control.Page as Control;
                if (container == null)
                    container = context.Handler as Control;

                string controlID = null;

                if (!string.IsNullOrEmpty(LookupOptions.ContainerID))
                {
                    string containerID = LookupOptions.ContainerID;

                    if (!string.IsNullOrEmpty(LookupOptions.PropertyName))
                    {
                        containerID = ControlHelper.AssembleControlID(LookupOptions.PropertyName, container);
                        /*if (containerID == null)
                            throw new Exception("No field is matching LookupOptions-PropertyName");*/
                    }

                    if (containerID != null) // found container
                    {
                        // New subcontainer
                        container = this.FindControlInContainer(container, containerID);
                        if (container == null)
                            throw new ArgumentException("No control is matching ContainerID");
                    }

                    if (string.IsNullOrEmpty(ControlID))
                        throw new ArgumentException("ControlID is mandatory when ContainerID is set");

                    /*Control child = ControlHelper.GetControlById(container, ControlID);

                    if (child != null)
                        controlID = child.UniqueID;*/

                    controlID = this.ControlID;
                }
                else
                {
                    if (!string.IsNullOrEmpty(LookupOptions.PropertyName))
                    {
                        if (!string.IsNullOrEmpty(ControlID))
                            throw new ArgumentException("The use of ControlID or LookupOptions-PropertyName properties is mandatory for this Parameter");
                        controlID = ControlHelper.AssembleControlID(LookupOptions.PropertyName, container);
                        /*if (controlID == null)
                            throw new Exception("No field is matching LookupOptions-PropertyName");*/
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(ControlID))
                            throw new ArgumentException("You have to choose between ControlID and LookupOptions-PropertyName for this Parameter");
                        controlID = this.ControlID;
                    }
                }

                if (controlID == null)
                    return null;

                //value = ControlHelper.GetControlValue(container, controlID);
                Control foundControl = this.FindControlInContainer(container, controlID);

                if (foundControl != null)
                {
                    if (!string.IsNullOrEmpty(this.PropertyName))
                    {
                        value = foundControl.GetPropertyValue(this.PropertyName);
                    }
                    else if (!foundControl.GetDefaultPropertyValue(out value))
                    {
                        throw (new NotSupportedException("Missing DefaultProperty for type " + foundControl.GetType().Name));
                    }
                }
            }
            catch (Exception ex)
            {
                throw new TargetException("Evaluation of ControlParameter encountered an error", ex);
            }

            return value;
        }

        /// <summary>
        /// Generic DOM research method
        /// </summary>
        /// <remarks>has to be overriden depending on the structure of your page model
        /// default implementation is matching System.Web.Controls</remarks>
        /// <param name="container"></param>
        /// <param name="controlId"></param>
        /// <returns></returns>
        public virtual Control FindControlInContainer(Control container, string controlID)
        {
            return container.FindControl(controlID);
        }

        #endregion
    }
}
